<?php
// +----------------------------------------------------------------------+
// | Restclient类                                                         |
// +----------------------------------------------------------------------+
// | Copyright (c) 2016-2017                                              |
// +----------------------------------------------------------------------+
// | Authors: Original chenwei <tochenwei@163.com>                        |
// +----------------------------------------------------------------------+

if(!class_exists('restclient')) {
    class restclient
    {
        private $ch;
        //public $http_code;
        private $_http_url;

        public $timeout = 10;
        public $connecttimeout = 30;
        public $ssl_verifypeer = false;

        public $contentFormat = 'text';
        private $_jsonKey        = '_j';
        private $_signKey        = '_sign';
        private $_reqTimeKey    = '_ts';
        public $contentNeedEncrypt    = false;
        public $contentNeedSign     = false;
        //是否需要发送访问者ip给对方
        public $needSendVisitorIp    = false;
        //是否需要加上时间戳
        public $needAddTimeStamp    = false;
        //是否需要返回的头部信息
        public $needReturnHeader      = false;
        public $http_header = array();
        private $postFields;

        private $_userAgent   = 'Mozilla/4.0 (compatible; MSIE .0; Windows NT 6.1; Trident/4.0; SLCC2;)';
        public $needUserAgent = false;
        //请求的token
        public static $token      = '2xI8xE109lsfA2r8s654103n1';
        //md5签名秘钥 william 20190305
        private static $_md5SignKey = '8902510f0e08828c50fae5329900e6580a09069d';

        public function __construct()
        {
            $this->ch = curl_init();
            if($this->needUserAgent){
                curl_setopt($this->ch, CURLOPT_USERAGENT, $this->_userAgent);
            }
            curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout);
            curl_setopt($this->ch, CURLOPT_TIMEOUT, $this->timeout);
            curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($this->ch, CURLOPT_AUTOREFERER, TRUE);
            curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, TRUE);
            //CURLOPT_SSL_VERIFYPEER 设置为FALSE 禁止 cURL 验证对等证书（peer’s certificate）
            curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer);
            curl_setopt($this->ch, CURLOPT_HEADERFUNCTION, array(
                $this,
                'getHeader'
            ));
            if($this->needReturnHeader){
                curl_setopt($this->ch, CURLOPT_HEADER, true);
            }
            if($this->needSendVisitorIp && !empty($_SERVER['REMOTE_ADDR'])) {
                $visitorIp = 'X-FORWARDED-FOR:' . $_SERVER['REMOTE_ADDR'];
                $this->setHttpHeader([$visitorIp]);
            }
        }

        /**
         * 生成签名
         * @param $key
         * @param array $params
         */
        private function _createSign($contentString)
        {
            return md5($contentString.self::$_md5SignKey);
        }

        /**
         * 获取数组转json后的字符串
         * @author william 20190305
         * @param array $params
         * @return string
         */
        private function _genJsonString(array $params)
        {
            if(isset($params[$this->_signKey])){
                unset($params[$this->_signKey]);
            }
            ksort($params);
            $string = '';
            foreach($params as $key => $value){
                $params[$key] = str_replace('&','',$value);
//                $string = $key . '=' . $value . '&';
            }
            $string = json_encode($params);
            return $string;
        }

        public function call($url, $method, $postFields = null, $http_header = [])
        {
            $this->_http_url = $url;
            //加上时间戳
            if($this->needAddTimeStamp){
                $this->http_header[$this->_reqTimeKey] = time();
            }
            $_params = array();
            if ($this->contentFormat == 'json') {
                $_params = json_encode($postFields, JSON_UNESCAPED_UNICODE);
                $this->http_header[] = 'Content-Type: application/json';
                $this->http_header[] = 'Content-Length: '. strlen($_params);
            } else {
                $_params = $postFields;
            }

            $this->postFields = $_params;
            $url = $this->to_url($method);
            is_object($this->ch) or $this->__construct();
            if(!empty($http_header)){
                $this->http_header = array_merge($this->http_header,$http_header);
            }

            if($this->http_header) {
                curl_setopt($this->ch, CURLOPT_HTTPHEADER, $this->http_header);
            }
            switch ($method) {
                case 'POST':
                    curl_setopt($this->ch, CURLOPT_POST, TRUE);
                    if ($this->postFields != null) {
                        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $this->postFields);
                    }
                    break;

                case 'DELETE':
                    curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
                    if ($this->postFields != null) {
                        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $this->postFields);
                    }
                    break;

                case 'PUT':
                    curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'PUT');
                    if ($this->postFields != null) {
                        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $this->postFields);
                    }
                    break;
            }
            curl_setopt($this->ch, CURLOPT_URL, $url);
            $response = curl_exec($this->ch);
            return $response;
        }
        
        // 获得加密后的url
        public function get_sign_url($url, $postFields,$method='GET'){
            
            $this->_http_url = $url;
            //加上时间戳
            $postFields[$this->_reqTimeKey] = time();
            $_params = array();
            if ($this->contentFormat == 'json') {
                foreach($postFields as $k=>$v){
                    $postFields[$k] = str_replace('&','',$v);
                }
                $reqContent = http_build_query($postFields);
                if (in_array($method, array('GET', 'POST'))) {
                    $_params[$this->_jsonKey] = $reqContent;
                } else {
                    $_params                   = $reqContent;
                }
                //curl_setopt($this->ch, CURLOPT_HTTPHEADER, array('Expect:  ','Content-Type: multipart/form-data;', 'Content-Length: ' . strlen($reqContent)));
            } else {
                $_params = $postFields;
            }
            
            $this->postFields = $_params;

            $url = $this->to_url('GET');
            return $url;
        }

        public function _POST($url, $params = null, $http_header = null)
        {
            return $this->call($url, 'POST', $params, $http_header);
        }

        public function _PUT($url, $params = null, $http_header = null)
        {

            return $this->call($url, 'PUT', $params, $http_header);
        }

        public function _GET($url, $params = null, $http_header = null)
        {
            return $this->call($url, 'GET', $params, $http_header);
        }

        public function _DELETE($url, $params = null, $http_header = null)
        {
            return $this->call($url, 'DELETE', $params, $http_header);
        }

        public function get_http_url()
        {
            $parts = parse_url($this->_http_url);
            $port = @$parts['port'];
            $scheme = $parts['scheme'];
            $host = $parts['host'];
            $path = @$parts['path'];
            $query = @$parts['query'] ? '?' . $parts['query'] : '';
            $port or $port = ($scheme == 'https') ? '443' : '80';
            if (($scheme == 'https' && $port != '443') || ($scheme == 'http' && $port != '80')) {
                $host = "$host:$port";
            }
            return "$scheme://$host$path$query";
        }

        public function to_url($method)
        {
            $out = $this->get_http_url();
            if ($method == 'GET') {
                $req_data = null;
                if($this->contentFormat != 'json'){
                    $req_data = in_array($method, array('PUT', 'DELETE')) ? $this->postFields : $this->to_postdata();
                }
                if(empty($req_data))return $out;
                if (!strpos($out, '?')) {
                    $out .= '?';
                }
                if (strpos($out, '?') && !strpos($out, '&')) {
                    $out .= '&';
                }
                $out .= $post_data;
            }
            return $out;
        }

        public function to_postdata()
        {
            return http_build_query($this->postFields);
        }

        public function close()
        {
            curl_close($this->ch);
        }

        public function setURL($url)
        {
            $this->url = $url;
        }

        public function setContentFormat($format = null)
        {
            if ($format == null) return false;
            $this->contentFormat = $format;
            return true;
        }

        //设置header william 20190228
        public function setHttpHeader($header = null)
        {
            if ($header == null) return false;
            $this->http_header = $header;
            return true;
        }

        //设置userAgent
        public function setUserAgent($userAgent = null)
        {
            if ($userAgent == null) return false;
            $this->_userAgent = $userAgent;
            return true;
        }

        /**
         * 生成授权码
         * @return string 授权码
         */
        private function setAuthorization()
        {
            return md5(substr(md5(self::$token), 8, 24) . self::$token);
        }

        public function setMethod($method)
        {
            $this->method = $method;
        }

        public function setParameters($params)
        {
            $this->postFields = $params;
        }

        public function getHeader($ch, $header)
        {
            $i = strpos($header, ':');
            if (!empty($i)) {
                $key = str_replace('-', '_', strtolower(substr($header, 0, $i)));
                $value = trim(substr($header, $i + 2));
                $this->http_header[$key] = $value;
            }
            return strlen($header);
        }

        /**
         * 关闭curl连接
         */
        public function __destruct()
        {
            curl_close($this->ch);
        }
    }
}
/**
header("Content-type: text/html; charset=utf-8");
$data = array('id'=>110,'amount'=>'20','info'=>'没错，就是三五警察在街上来回的“溜达”
　　最近，有网友不理解警察这样“溜达”有什么作用，于是向中国<<警察>>网发起了提问：');

$url   = 'http://www.testhrguo.cc/rest/server.php';
$client = new restClient;
$result = $client->_GET($url,$data);
print_r($result);
$result = $client->_POST($url,$data);
print_r($result);
$result = $client->_PUT($url,$data);
print_r($result);
$result = $client->_DELETE($url,$data);
print_r($result);
*/
?>